package mud;

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlID;

/** A location in the virtual world */
public class Room extends Entity {

    /** the id of the room */
    @SuppressWarnings("unused")
    @XmlAttribute
    @XmlID
    private String id;
    
    /** a brief, one line description of the room */
    @XmlAttribute
    private String name;
    
    /** the full description of the room */
    @XmlElement
    private String appearance;
    
    /** the exits which lead from this room */
    @XmlElement(name="exit")
    private List<Exit> exits;
    
    /** the units currently occupying this room */
    private final List<Entity> occupants;

    /**
     * Constructor
     */
    public Room() {
        occupants = new ArrayList<>();
    }
    
    /**
     * Adds an occupant to the room and updates observers
     * @param entity the occupant to add
     */
    public void addOccupant(Entity entity) {
        assert !occupants.contains(entity);
        
        for (Entity occupant : occupants) {
            if (occupant instanceof Observer) {
                entity.addObserver((Observer) occupant);
            }
            if (entity instanceof Observer) {
                occupant.addObserver((Observer) entity);
            }
        }
        
        occupants.add(entity);
    }
    
    /**
     * Removes an occupant from the room and updates observers
     * @param entity the occupant to remove
     */
    public void removeOccupant(Entity entity) {
        assert occupants.contains(entity);
        
        occupants.remove(entity);

        for (Entity occupant : occupants) {
            if (occupant instanceof Observer) {
                entity.removeObserver((Observer) occupant);
            }
            if (entity instanceof Observer) {
                occupant.removeObserver((Observer) entity);
            }
        }
    }

    @Override 
    public String toString() {
        return getClass().getSimpleName() + "["
            + "name=" + name + ","
            + "occupants=" + occupants +  "]";
    }
    
    /**
     * @return the entities currently occupying this room
     */
    public List<Entity> getOccupants() {
        return occupants;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public String getType() {
        return "room";
    }

    @Override
    public String getAppearance() {
        return appearance;
    }

    /**
     * @return the exits which lead from this room
     */
    public List<Exit> getExits() {
        return exits;
    }

    /**
     * Returns the exit in a given direction if one exists
     * @param direction the direction
     * @return the exit, or null
     */
    public Exit getExit(Direction direction) {
        for (Exit exit : exits) {
            if (direction.toString().equalsIgnoreCase(exit.getName())) {
                return exit;
            }
        }   
        return null;
    }
}
